////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    PenguinPowerGuts.cpp                                         //
//  Developer:   Phillip Sharpless                                            //
//  Create date: 05/11/2006                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class implementation for the slot gut of the     //
//               Australian Slot machine called Penguin Power                 //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2006 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#include "PenguinPowerGuts.h"
#include <math.h>

////////////////////////////////////////////////////////////////////////////
/// PenguinPowerGuts::m_aLineWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by wheel icon and then count.  So to get the
/// SpinResult for 5 Seals, use the following code snippet:
///
///		SpinResult result = m_aLineWinSpinResults[ ICON_SEAL ][ 5 ];
///
/// In this example result would be set to EVT_FIVE_SEAL.
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::SpinResult PenguinPowerGuts::m_aLineWinSpinResults[][6] = 
{
// Number of icons:			0			1			2					3						4						5
/* ICON_NINE */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_NINE,			EVT_FOUR_NINE,			EVT_FIVE_NINE		},
/* ICON_TEN */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_TEN,			EVT_FOUR_TEN,			EVT_FIVE_TEN		},
/* ICON_JACK */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_JACK,			EVT_FOUR_JACK,			EVT_FIVE_JACK		},
/* ICON_QUEEN */		{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_QUEEN,		EVT_FOUR_QUEEN,			EVT_FIVE_QUEEN		},
/* ICON_KING */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_KING,			EVT_FOUR_KING,			EVT_FIVE_KING		},
/* ICON_ACE */			{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_THREE_ACE,			EVT_FOUR_ACE,			EVT_FIVE_ACE		},
/* ICON_EGG */			{	EVT_LOSER,	EVT_LOSER,	EVT_TWO_EGG,		EVT_THREE_EGG,			EVT_FOUR_EGG,			EVT_FIVE_EGG		},
/* ICON_FISH */			{	EVT_LOSER,	EVT_LOSER,	EVT_TWO_FISH,		EVT_THREE_FISH,			EVT_FOUR_FISH,			EVT_FIVE_FISH		},
/* ICON_SEAL */			{	EVT_LOSER,	EVT_LOSER,	EVT_TWO_SEAL,		EVT_THREE_SEAL,			EVT_FOUR_SEAL,			EVT_FIVE_SEAL		},
/* ICON_PENGUIN */		{	EVT_LOSER,	EVT_LOSER,	EVT_TWO_PENGUIN,	EVT_THREE_PENGUIN,		EVT_FOUR_PENGUIN,		EVT_FIVE_PENGUIN	},
/* ICON_IGLOO    */		{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_LOSER,				EVT_LOSER			},
/* ICON_BABY_PENGUIN */	{	EVT_LOSER,	EVT_LOSER,	EVT_LOSER,			EVT_LOSER,				EVT_LOSER,				EVT_LOSER			} 
};

////////////////////////////////////////////////////////////////////////////
/// PenguinPowerGuts::m_aScatterWinSpinResults
///
/// This array is used to quickly get the SpinResult for the number of
/// icons.  It is indexed by icon count only, since Igloos are the only
/// scatter win.  So to get the SpinResult for 5 Igloos, use the
/// following code snippet:
///
///		SpinResult result = m_aScatterWinSpinResults[ 5 ];
///
/// In this example result would be set to EVT_FIVE_IGLOO.
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::SpinResult PenguinPowerGuts::m_aScatterWinSpinResults[6] = 
{
	// ICON_IGLOO			Number of Icons
	EVT_LOSER,				// 0
	EVT_SCATTER_NEAR_MISS,	// 1
	EVT_TWO_IGLOO,			// 2
	EVT_THREE_IGLOO,		// 3
	EVT_FOUR_IGLOO,			// 4
	EVT_FIVE_IGLOO			// 5
};

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::PenguinPowerGuts()   
///
/// This is the default constructor for the class.
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::PenguinPowerGuts()
{
	// If this doesn't compile it means that someone probably added
	// another icon type but did not update the
	// m_aLineWinSpinResults array. 
	C_ASSERT( countof( m_aLineWinSpinResults ) == NUM_VALID_ICONS );

}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::~PenguinPowerGuts()
///
/// Destructor for PenguinPowerGuts. 
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::~PenguinPowerGuts()
{
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::classifyStops()   
///
/// @param   stops      The array of stop positions for the line.
/// @param   bet        The value of the line bet.
/// @param   line       The index of the line.  
///
/// This helper method is used to calculate the payout on a line.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::classifyStops( SpinLine* spinline, uint8* stops, uint8 bet, uint8 line,
	uint8& rtnresult, uint8& multiplier )
{
	// Start with the icon on the first reel of the payline
	uint8 testIcon = getIcon( getGameModeId(), 0, stops[0] )->iconid;

	// Declare a local variable to track whether or not we found a substitution.
	bool bSubstitution = false;

	// See what the spin result is if we used any Baby Penguins as substitution symbols.

	rtnresult = getLineWinResultWithPossibleSubstitution( stops, testIcon, bSubstitution );

	// If we did actually have a substitution and a winning spin...
	if (bSubstitution && rtnresult != EVT_LOSER )
	{
		// then add a note and change the multiplier.
		spinline->addNote( NOTE_BABY_PENGUIN_SUBSTITUTION );
		multiplier = MULTIPLIER_BABY_PENGUIN_SUBSTITUTION;
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::SpinResult PenguinPowerGuts::getLineWinResultWithPossibleSubstitution( uint8* stops, uint8 testIcon, bool& bSubstitution ) const
///
/// @param   stops			The array of stop positions for the line.
/// @param   testIcon		The icon we are looking for, typically the first icon on the line.
/// @param   bSubstitution	An output parameter that is set if a subsitution is used.
///
/// @return	 SpinResult				A payout from the SpinResult enumeration.
///
/// This helper method is used to calculate the line win payout, including possible substitution.
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::SpinResult PenguinPowerGuts::getLineWinResultWithPossibleSubstitution(
	uint8* stops, uint8 testIcon, bool& bSubstitution ) const
{
	// Initialize the out parameter
	bSubstitution = false;

	// Loop through the remaining reels until the streak is over
	for ( int i = 1; i < getReelCount(); i++ )
    {
		// See what this icon is.
		uint8 currentIcon = getIcon( getGameModeId(), i, stops[i] )->iconid;

		// If the current icon is a Baby Penguin
		if ( currentIcon == ICON_BABY_PENGUIN )
		{
			// then use it as a substitution symbol and continue on.
			bSubstitution = true;
			continue;
		}
		// Otherwise if the test icon is a Baby Penguin
		else if ( testIcon == ICON_BABY_PENGUIN )
		{
			// then we still have a substitution.  In this case the line
			// started out with the substitution symbol.
			bSubstitution = true;

			// We have now found our first icon that is not a substitution symbol.
			// All of the rest of the icons will have to match this one now for the
			// streak to continue, so change our test icon.
			testIcon = currentIcon;
			continue;
		}

		// If the current icon is not the test icon...
        if ( currentIcon != testIcon )
        {
			// then the streak is over so break out of the loop
			break;
        }
    }

	// Use the array to look up the spin result for i testIcons.
	return lookupLineWinSpinResult( testIcon, i );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::classifyScatters( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This is an override of the framework method.  
/// It determines if the current spin merits free spins or scatter payments.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::classifyScatters( SlotSpin* spin )
{	
	// Try for the Random Progressive Jackpot
	tryForJackpot(spin);

	int32 nScatterPositions = 0;

	SpinResult srResult = getScatterWinResult(spin, nScatterPositions);

	// Add the scatter, if any.
	evaluateScatterWin(spin, srResult, nScatterPositions);

	// See if we triggered the Penguin Slide Feature
	evaluatePenguinSlide( spin, nScatterPositions );

	// See if we triggered the free game feature.
	evaluateFeatureTrigger( spin, srResult, nScatterPositions );
}

////////////////////////////////////////////////////////////////////////////
/// @fn		PenguinPowerGuts::tryForJackpot()
///
///	This function tries to win the jackpot and adds the scatter if we hit
/// the jackpot.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::tryForJackpot( SlotSpin* spin )
{
	// If we are in the first paid spin (NOT a bonus spin)...
	if ( getGameModeId() == MODE_NORMAL ) 
	{
		// then try for the Random Progressive Jackpot
		// If we hit the jackpot...
		if ( getRandomProgressiveJackpotResult( spin->getSpinLineCount() ) || 
			m_bForceRandomJackpot)
		{
			// then add a jackpot scatter to the spin.
			spin->addScatter( 0, getPayout( EVT_RANDOM_PROGRESSIVE_WINNER )->payoutAmount, 1,
				true, EVT_RANDOM_PROGRESSIVE_WINNER, 0 );
		}
    }
}

////////////////////////////////////////////////////////////////////////////
/// @fn		PenguinPowerGuts::getScatterWinResult()
///
/// @param   spin				The spin we are evaluating.
/// @param   scatterPositions	An output parameter that contains a bit mask for the icon positions.
///
/// @return	 SpinResult			A payout from the SpinResult enumeration.
///
///	This function looks for scatter wins.
////////////////////////////////////////////////////////////////////////////
PenguinPowerGuts::SpinResult PenguinPowerGuts::getScatterWinResult( SlotSpin* spin, int32& scatterPositions) const
{
	// Keep up with how many scatter icons we found.
	uint8 numScatterIcons = 0;

	// Loop through each reel.
  	for( int reel = 0; reel < getReelCount(); reel++ )
	{
		// The position bit for the current icon in case it needs to be stored in a mask.
		uint8 position = reel;

		// Keep up with whether or not we found a scatter icon on this reel.
		bool bFoundScatterIconOnReel = false;

		// Loop through each row in the wheel house.
		for( int row = 0; row < 3; row++ )
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel, spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;
			
			// If the icon is an Igloo...
			if ( currentIcon == ICON_IGLOO )
			{
				// Set the flag so that we know we found a scatter icon on this reel.
				bFoundScatterIconOnReel = true;
			}

			// If we found a scatter icon...
			if ( bFoundScatterIconOnReel )
			{
				// then increase the scatter icon count
				numScatterIcons++;

				// Set the bit in the position mask for this stop.
				scatterPositions |= 1 << position;

				// Break out now.
				break;
			}

			// Move to the next bit in the position mask.
            position += 5;
		}
	}

	// Use the array to look up the spin result in the current game mode.
	return lookupScatterWinSpinResult( numScatterIcons );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::evaluateScatterWin()
///
/// This function determines if the current spin wins a scatter payment and
/// adds the scatter.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::evaluateScatterWin( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions)
{
	// If we got the scatter win (or almost got it)
	if ( srScatterResult != EVT_LOSER )
	{
		// Get the base payout for the scatter.
		int32 nPayout = getPayout( srScatterResult )->payoutAmount;
		
		// Scatters payout based on the total bet, so factor in the number of bet lines.
		nPayout *= spin->getSpinLineCount();

		// Default to no multiplier.
		int32 nMultiplier = 1;


		// Add the payout to the total win for this spin.
		increaseTotalWin( nPayout * nMultiplier );
    
		// Add a scatter to the spin.
		spin->addScatter( scatterPositions, nPayout * getBetPerLine(), nMultiplier, 
						  false, srScatterResult, 0 );
	}
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::evaluateFeatureTrigger()
///
/// This function determines if the current spin triggers the free game
///	feature and adds the scatter.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::evaluateFeatureTrigger( SlotSpin* spin, SpinResult srScatterResult, int32 scatterPositions )
{
	//feature cannot be retriggered
	if(getGameModeId() != MODE_NORMAL)
	{
		return;
	}

	// We need a place to keep up with how many free spins to award.
	int32 nFreeSpins = 0;

	// Figure out how many free spins they get.

	if ( srScatterResult == EVT_THREE_IGLOO || 
		 srScatterResult == EVT_FOUR_IGLOO ||
		 srScatterResult == EVT_FIVE_IGLOO )
	{
		nFreeSpins = getRandomValueFromProbabilityTable( PROBABILITY_TABLE_FREE_SPINS );

		if(m_bDebugSpinsMode)
		{
			if(g_nFeatureSpins != -1)
			{
				nFreeSpins = g_nFeatureSpins;
				g_nFeatureSpins = -1;
			}
		}
	}
	else
	{
		return;
	}

	// Change the game mode.
	setGameModeId( MODE_FREE_SPIN );

	// Add the free spins.
	incrementFreeSpins( nFreeSpins );

	// Add a scatter to the spin for the feature trigger.
	spin->addScatter( scatterPositions, 0, 0, false,
		EVT_FREE_GAMES, nFreeSpins );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::evaluatePenguinSlide()
///
/// This function determines if any Baby Penguin slide(s) scenarios have occured 
///  and awards a scatter win for each slide if so
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::evaluatePenguinSlide( SlotSpin* spin, int32 scatterPositions )
{
	//slide cannot be triggered in regular mode
	if(getGameModeId() == MODE_NORMAL)
	{
		return;
	}

	// Loop through each row in the wheel house.
	for( int row = 0; row < 3; row++ )
	{
		//check reel 1, 2, and 3 for baby penguins
		for(int reel=1; reel < 4; reel++)
		{
			// Get the current stop.
			uint8 stop = relativeWheelPosition( getGameModeId(), reel, spin->getStops()[ reel ], row );

			// Get the icon for the current stop.
			uint8 currentIcon = getIcon( getGameModeId(), reel, stop )->iconid;

			//we have a baby penguin, check for igloos on reels 0 and 5
			if(currentIcon == ICON_BABY_PENGUIN)
			{
				int first_igloo = scatterPositions & (int) pow(2.0,5*row);
				int last_igloo = scatterPositions & (int) pow(2.0,5*(row+1) - 1);

				//first igloo has a prize
				if(first_igloo)
				{
					int32 nFreeSpins = 0;
					int32 nPayout = 0;

					int slide_prize_index = getRandomValueFromProbabilityTable( PROBABILITY_TABLE_PENGUIN_PRIZE );

					if(m_bDebugSpinsMode)
					{
						if(g_nSlidePrize != SLIDE_PRIZE_NONE)
						{
							slide_prize_index = g_nSlidePrize;
						}
					}

					switch(slide_prize_index)
					{
						case 0:
							nPayout = 5;
							break;
						case 1:
							nPayout = 10;
							break;
						case 2:
							nPayout = 25;
							break;
						case 3:
							nPayout = 100;
							break;
						case 4:
							nFreeSpins = 2;
							break;
						case 5:
							nFreeSpins = 3;
							break;
						case 6:
							nFreeSpins = 5;
							break;
						case 7:
							nFreeSpins = 10;
							break;

						default:
							ASSERT(0);
					}

					if(nFreeSpins)
					{
						incrementFreeSpins( nFreeSpins );
					}

					if(nPayout)
					{
						nPayout *= spin->getSpinLineCount();
						increaseTotalWin( nPayout );
					}

					int32 slide_scat_positions = 0;

					//add the baby penguin into the scatter mask
					slide_scat_positions += (int) pow(2.0,5*row + reel);

					if(first_igloo)
						slide_scat_positions += (int) pow(2.0,5*row);

					// Add a scatter to the spin.
					spin->addScatter( slide_scat_positions, nPayout * getBetPerLine(), 
										1, false, EVT_BABY_PENGUIN_SLIDE, nFreeSpins );
				}

				//last igloo has a prize
				if(last_igloo)
				{
					int32 nFreeSpins = 0;
					int32 nPayout = 0;

					int slide_prize_index = getRandomValueFromProbabilityTable( PROBABILITY_TABLE_PENGUIN_PRIZE );

					if(m_bDebugSpinsMode)
					{
						if(g_nSlidePrize != SLIDE_PRIZE_NONE)
						{
							slide_prize_index = g_nSlidePrize;
						}
					}

					switch(slide_prize_index)
					{
						case 0:
							nPayout = 5;
							break;
						case 1:
							nPayout = 10;
							break;
						case 2:
							nPayout = 25;
							break;
						case 3:
							nPayout = 100;
							break;
						case 4:
							nFreeSpins = 2;
							break;
						case 5:
							nFreeSpins = 3;
							break;
						case 6:
							nFreeSpins = 5;
							break;
						case 7:
							nFreeSpins = 10;
							break;

						default:
							ASSERT(0);
					}

					if(nFreeSpins)
					{
						incrementFreeSpins( nFreeSpins );
					}

					if(nPayout)
					{
						nPayout *= spin->getSpinLineCount();
						increaseTotalWin( nPayout );
					}

					int32 slide_scat_positions = 0;

					//add the baby penguin into the scatter mask
					slide_scat_positions += (int) pow(2.0,5*row + reel);

					if(last_igloo)
						slide_scat_positions += (int) pow(2.0,5*(row+1) - 1);

					// Add a scatter to the spin.
					spin->addScatter( slide_scat_positions, nPayout * getBetPerLine(), 
										1, false, EVT_BABY_PENGUIN_SLIDE, nFreeSpins );
				}
			}

		}
	}

	//reset debug data
	if(m_bDebugSpinsMode)
		g_nSlidePrize = SLIDE_PRIZE_NONE;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::isValidGuts()   
///
/// @return	 bool8      True if gut is valid.    
///
/// This helper method is used to see if the current gut ID is valid.
////////////////////////////////////////////////////////////////////////////
bool8 PenguinPowerGuts::isValidGuts()
{
	// Make sure that the m_aLineWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	// Note:  we can't do this in the constructor because we have to call
	// getReelCount.
	ASSERT( countof( m_aLineWinSpinResults[0] ) == getReelCount( MODE_NORMAL ) + 1 );

	// Make sure that the m_aScatterWinSpinResults array has an entry for each reel,
	// and an additional entry in case there are 0 icons on the line.
	ASSERT( countof( m_aScatterWinSpinResults ) == getReelCount( MODE_NORMAL ) + 1 );

	// Now make sure that both game modes have the same number of reels.
	ASSERT( getReelCount( MODE_NORMAL ) == getReelCount( MODE_FREE_SPIN ) );

	// Finally just check to see if the gut is within the right range.
    return ( getGutsId() >= 3600 && getGutsId() < 3700 );
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )
///
/// @param   nGameModeMultiplier	The multiplier for the game mode.
/// @param   nNoteId				The note ID for the game mode.
///
/// This helper method is used to get the game mode multiplier and note ID.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier,
	uint8& nNoteId )
{
	// If we are in free spin mode...
    if ( getGameModeId() == MODE_FREE_SPIN )
    {

    }
	// Otherwise...
    else
    {
		// just defer to the base class.
        SlotGuts::getGameModeMultiplierAndNoteId(nGameModeMultiplier, nNoteId );
    }
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::preSpinClassifyResults( SlotSpin* spin )
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden in debug spins mode to alter the reel stops.
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::preSpinClassifyResults( SlotSpin* spin )
{
	SlotGuts::preSpinClassifyResults(spin);
	return;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PenguinPowerGuts::Debug_SetLoserStops( uint8* pStops )
///
/// @param   pStops		The stops to set.
///
/// Base class override, returns a losing spin triggered by the debug tool
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::Debug_SetLoserStops( uint8* pStops )
{
	pStops[0]=4;
	pStops[1]=0;
	pStops[2]=0;
	pStops[3]=0;
	pStops[4]=0;
}

////////////////////////////////////////////////////////////////////////////
/// Debug spins functionality, can control how many free spins are won
/// in normal mode and what prizes are won by the baby penguin slides
////////////////////////////////////////////////////////////////////////////
void PenguinPowerGuts::initDebugFunctionMap()
{
	SlotGuts::initDebugFunctionMap();

	addDebugStopFunction( EVT_DEBUG_FUNCTION_5_SPIN, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_FiveSpins) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_10_SPIN, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_TenSpins) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_15_SPIN, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_FifteenSpins) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_25_SPIN, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_TwentyFiveSpins) );


	addDebugStopFunction( EVT_DEBUG_FUNCTION_5X_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_5X) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_10X_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_10X) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_25X_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_25X) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_100X_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_100X) );


	addDebugStopFunction( EVT_DEBUG_FUNCTION_2S_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_2S) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_3S_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_3S) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_5S_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_5S) );

	addDebugStopFunction( EVT_DEBUG_FUNCTION_10S_PRIZE, 
		new DebugStopFunc<PenguinPowerGuts>(this, &PenguinPowerGuts::DebugFeature_Prize_10S) );
}

int PenguinPowerGuts::g_nFeatureSpins = -1;
int PenguinPowerGuts::g_nSlidePrize = SLIDE_PRIZE_NONE;

void PenguinPowerGuts::DebugFeature_FiveSpins( SlotSpin *spin )
{
    g_nFeatureSpins = 5;
}

void PenguinPowerGuts::DebugFeature_TenSpins( SlotSpin *spin )
{
    g_nFeatureSpins = 10;
}

void PenguinPowerGuts::DebugFeature_FifteenSpins( SlotSpin *spin )
{
    g_nFeatureSpins = 15;
}

void PenguinPowerGuts::DebugFeature_TwentyFiveSpins( SlotSpin *spin )
{
    g_nFeatureSpins = 25;
}

void PenguinPowerGuts::DebugFeature_Prize_5X( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_5_CREDIT;
}

void PenguinPowerGuts::DebugFeature_Prize_10X( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_10_CREDIT;
}

void PenguinPowerGuts::DebugFeature_Prize_25X( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_25_CREDIT;
}

void PenguinPowerGuts::DebugFeature_Prize_100X( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_100_CREDIT;
}

void PenguinPowerGuts::DebugFeature_Prize_2S( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_2_FREE_GAME;
}

void PenguinPowerGuts::DebugFeature_Prize_3S( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_3_FREE_GAME;
}

void PenguinPowerGuts::DebugFeature_Prize_5S( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_5_FREE_GAME;
}

void PenguinPowerGuts::DebugFeature_Prize_10S( SlotSpin *spin )
{
	g_nSlidePrize = SLIDE_PRIZE_10_FREE_GAME;
}